#include <iostream>
#include <memory>
#include <functional>
#include <unistd.h>
#include <vector>
#include <string>
#include <unordered_map>

using func_t = std::function<void()>;
using remove_t = std::function<void()>;

namespace zj
{
    class TimerTask
    {
    public:
        TimerTask(uint64_t id, func_t cb, int delay) : _id(id), _cb(cb), _delay(delay), _canceled(false)
        {
        }

        ~TimerTask()
        {
            if (_canceled == false)
                _cb();
            _remove_cb();
        }

        void Setremove(const remove_t &cb)
        {
            _remove_cb = cb;
        }
        void Cancel() { _canceled = true; }
        int Delay()
        {
            return _delay;
        }

    private:
        uint64_t _id;        // 用来查找TimerTask的
        func_t _cb;          // 任务的回调函数
        remove_t _remove_cb; // 清除定时器在weakptr_map中的副本
        int _delay;          // 这个定时任务的延迟时间
        bool _canceled;      // false-表示没有被取消， true-表示被取消
    };

    class TimeWheel
    {
    public:
        using WeakTask = std::weak_ptr<TimerTask>;
        using PtrTask = std::shared_ptr<TimerTask>;
        TimeWheel() : _capacity(60), _timer(0), _wheel(_capacity)
        {
        }

        void TimerCancel(uint64_t id)
        {
            auto it = _weakptr_map.find(id);
            if (it == _weakptr_map.end())
            {
                return;
            }
            PtrTask pt = it->second.lock();
            if (pt)
                pt->Cancel();
        }
        void SetRemove(uint64_t id)
        {
            auto it = _weakptr_map.find(id);
            if (it != _weakptr_map.end())
            {
                _weakptr_map.erase(it);
            }
        }

        void addTimer(uint64_t id, func_t cb, int delay)
        {
            PtrTask ptr = std::make_shared<TimerTask>(id, cb, delay);
            ptr->Setremove(std::bind(&TimeWheel::SetRemove, this, id)); // 设置remove
            int pos = (_timer + delay) % _capacity;                     // 计算位置

            _wheel[pos].push_back(ptr);
            _weakptr_map[id] = WeakTask(ptr);
        }

        void TimerRefresh(uint64_t id) // 刷新定时任务
        {
            auto it = _weakptr_map.find(id);
            if (it == _weakptr_map.end())
            {
                return;
            }
            PtrTask ptr = _weakptr_map[id].lock();
            int pos = (ptr->Delay() + _timer) % _capacity;
            _wheel[pos].push_back(ptr); // 定时任务就是在适当位置在构造一个PtrTask ptr
        }

        // 这个函数应该每秒钟被执行一次，相当于秒针向后走了一步

        void RunTimerTask()
        {
            _timer = (_timer + 1) % _capacity;
            _wheel[_timer].clear(); // 清空指定位置的数组，就会把数组中保存的所有管理定时器对象的shared_ptr释放掉
        }

        ~TimeWheel()
        {
        }

    private:
        int _capacity;                                       // 定时器存储的大小
        int _timer;                                          // 当前指向的位置 指向哪个位置就清除哪个位置的定时器
        std::unordered_map<uint64_t, WeakTask> _weakptr_map; // 用来提供给刷新定时器任务时，创建TimerTask*的副本
        std::vector<std::vector<PtrTask>> _wheel;            // 真正的定时器存储
    };
};
